package com.kotlin.demo.泛型
//1.标记为 in out 有什么好处(没有这两个关键字之前有什么问题)

/**
 * 如果泛型类型,只作为函数的返回类型,那么泛型可以标记为 out
 */
interface Production<out T> {
    fun produce(): T
}

/**
 * 如果泛型类型,只作为函数的参数,那么泛型类型,可以标记为 in
 * in 作为消费类型,我连最高类型都能消费,呢最高类型的子类肯定也不再话下
 */
interface Consumer<in T> {
    fun consume(item: T)
}

/**
 * 如果泛型类 即将泛型类型作为函数参数(就是输入,调用函数就是输入),又将泛型类型作为函数的输出()
 * 那么这个泛型类型前面 既不能用 in 也不能用out
 */
interface ProductionAndConsumer<T> {
    fun produce(): T
    fun consume(item: T)
}

open class Food
open class FastFood() : Food()
class Burger() : FastFood()

class FoodFactory : Production<Food> {
    override fun produce(): Food {
        println("produce a food")
        return Food()
    }
}

class FastFoodFactory : Production<FastFood> {
    override fun produce(): FastFood {
        println("produce a fastFood")
        return FastFood()
    }
}

class BurgerFactory : Production<Burger> {
    override fun produce(): Burger {
        println("produce a burger")
        return Burger()
    }
}

class EveryBody : Consumer<Food> {
    override fun consume(item: Food) {
        println("everybody eat food")
    }
}

class ModernPeople : Consumer<FastFood> {
    override fun consume(item: FastFood) {
        println("modernPeople eat fastFood")
    }
}

class American : Consumer<Burger> {

    override fun consume(item: Burger) {
        println("american eat hamburger")
    }

}


fun main() {
    /**
     * 对于out类型 我们能够使用子类泛型的对象 赋值给使用父类泛型的对象
     */
    val foodFactory: Production<Food> = FoodFactory()
    val fastFoodFactory: Production<Food> = FastFoodFactory()
    // BurgerFactory() 泛型对象是 Burger 可以赋值给 burgerFactory(Production<Food>)使用的是父类泛型对象
    val burgerFactory: Production<Food> = BurgerFactory() // 定义的是我能生产Hamburger,我用一个生产Food 的类型肯定能表示我


    /**
     * 对于 in 泛型,我们能够使用父类泛型对象赋值给使用子类泛型的对象
     * 为什么能这么用:  这边的泛型类型全部作为参数
     */
    val everyBody: Consumer<Burger> = EveryBody() //我连Food都能消费,消费个Burger 肯定没问题
    val modernPeople: Consumer<Burger> = ModernPeople()
    val american: Consumer<Burger> = American() // 我定义的最高消费类型就是Hamburger,如果让我消费Food 我就消费不了

    /**
     * 泛型只作为参数使用,那么是消费类型,使用in 定义,
     */



}















